#!/bin/bash

usage="\
Usage:
	oc-ops misc tracesig [-p pid| -c comm | -s sig] -e|-d|-r
        COMMAND-LINE Options:
	-p,	设置要跟踪的接收信号进程pid
	-s,	只跟踪某个信号
	-d,	结束跟踪
	-r,	查看信号发送信息	
"

if (( $# < 1 )); then
	echo "$usage"
	exit 1
fi

export logdir="/data/oc-ops/misc/tracesig"

export curr_dir=$(pwd)
export work_dir=$(readlink /proc/$$/fd/255); work_dir=$(dirname $work_dir); cd "$work_dir"
export run_log="$logdir/run_log"

source lib.sh
set_cgroup_rights

tracee_pid=0
tracee_sig=0

check_logdir()
{
	echo "$logdir" | grep ^[/] > /dev/null ; local ret_val=$?
	if (( $ret_val != 0 )); then echo "Must using absolute path!";  return 1 ; fi

	echo "$logdir" | grep "misc/tracesig" > /dev/null ; ret_val=$?
	if (( $ret_val != 0 )); then echo "Path must including \"misc/tracesig\" substring!"; return 1 ; fi

	echo "$logdir" | grep -E '[ |        ]' > /dev/null ; ret_val=$?
	if (( $ret_val == 0 )); then echo "Path must not including space and tab char!"; return 1 ; fi

	return 0
}

safe_rm()
{
	echo "$PWD/" | grep "$logdir" > /dev/null ; local ret_val=$?
	if (( $ret_val != 0 )); then echo "Forbid rm outside the $logdir dir!";  return 1 ; fi

	echo "$@" | grep "/" > /dev/null ; ret_val=$?
	if (( $ret_val == 0 )); then echo "Forbid having \"/\" in args!";  return 1 ; fi

	rm $@ 2>/dev/null
}
export -f safe_rm

mkdir -p "$logdir"

filter="--filter"
get_filter()
{
	if (( $tracee_pid != 0 )); then
		if (( $tracee_sig != 0 )); then
			filter=$( echo "$filter 'pid == $tracee_pid && sig == $tracee_sig'")
			return
		else
			filter=$( echo "$filter 'pid == $tracee_pid'")
		fi
	fi

	if (( $tracee_sig != 0 )); then
			filter=$( echo "$filter 'sig == $tracee_sig'")
	fi
}

perf_pid=""
enable_trace()
{
	check_logdir ; cd $logdir
	safe_rm -f *
	get_filter
	perf_cmd="perf record -e signal:signal_generate $filter &"
	eval $perf_cmd
	perf_pid=$!
	echo $perf_pid > perf_pid
}

disable_trace()
{
	check_logdir ; cd $logdir
	perf_pid=$(cat perf_pid)
	kill -15 $perf_pid
}

read_trace_result()
{
	check_logdir ; cd $logdir
	perf script
}

while getopts 'p:s:edrh' OPT; do
        case $OPT in
                p) 	tracee_pid="$OPTARG"	
                        ;;
		s)	tracee_sig="$OPTARG"
			;;
		d)	disable_trace
			exit 0
			;;
		r)	read_trace_result
			exit 0
			;;
                h)	echo "$usage"
                        exit $?
			;;
                ?)	echo "Invalid option: $OPT" >&2
                        echo "$usage"
                        exit 1
			;;
        esac
done

enable_trace
